package com.brs.model;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

public class Library {
    private String name;
    private String location;
    private Date openTime;
    private Date closeTime;
    private int totalSits;
    private int availableSits;
    private ArrayList<Issue> issues = new ArrayList<>();
    private ArrayList<Manager> managers = new ArrayList<>();
    private ArrayList<Borrower> borrowers = new ArrayList<>();
    private ArrayList<BookItem> bookItems = new ArrayList<>();

    public static final int OUT_OF_SIT = -1;

    private static Library library;

    public static Library getInstance() {
        if (library == null) {
            library = new Library();
        }
        return library;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public Date getOpenTime() {
        return openTime;
    }

    public void setOpenTime(Date openTime) {
        this.openTime = openTime;
    }

    public Date getCloseTime() {
        return closeTime;
    }

    public void setCloseTime(Date closeTime) {
        this.closeTime = closeTime;
    }

    public int getTotalSits() {
        return totalSits;
    }

    public void setTotalSits(int totalSits) {
        this.totalSits = totalSits;
        this.availableSits = totalSits;
    }

    public int getAvailableSits() {
        return availableSits;
    }

    public ArrayList<Issue> getIssues() {
        return issues;
    }

    public void setIssues(ArrayList<Issue> issues) {
        this.issues = issues;
    }

    public ArrayList<Manager> getManagers() {
        return managers;
    }

    public void setManagers(ArrayList<Manager> managers) {
        this.managers = managers;
    }

    public ArrayList<Borrower> getBorrowers() {
        return borrowers;
    }

    public void setBorrowers(ArrayList<Borrower> borrowers) {
        this.borrowers = borrowers;
    }

    public ArrayList<BookItem> getBookItems() {
        return bookItems;
    }

    public void setBookItems(ArrayList<BookItem> bookItems) {
        this.bookItems = bookItems;
    }

    public static Library getLibrary() {
        return library;
    }

    public static void setLibrary(Library library) {
        Library.library = library;
    }

    public boolean isOpen(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        try {
            // Just compare hour and minute, ignore date(they're `today`!)
            Date now = sdf.parse(sdf.format(date));
            Date open = sdf.parse(sdf.format(openTime));
            Date close = sdf.parse(sdf.format(closeTime));
            if (now.after(open) && now.before(close)) {
                return true;
            }
        } catch (ParseException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        return false;
    }

    public synchronized int occupySit() {
        if (availableSits <= 0) {
            return OUT_OF_SIT;
        }
        availableSits--;
        return availableSits;
    }

    public void releaseSit() {
        if (availableSits < totalSits) {
            availableSits++;
        }
    }

    public int getTotalBooks() {
        return bookItems.size();
    }

    public ArrayList<BookItem> searchBooks(String keyword) {
        ArrayList<BookItem> books = new ArrayList<>();
        for (BookItem book : library.bookItems) {
            // Fuzzy search with keywords
            if (book.getISBN().contains(keyword) || book.getTitle().contains(keyword)
                    || book.getCatagory().contains(keyword) || book.getAuthor().contains(keyword)
                    || book.getPublisher().contains(keyword)) {
                books.add(book);
            }
        }
        return books;
    }

    public ArrayList<BookItem> searchBooks(int barCode) {
        ArrayList<BookItem> books = new ArrayList<>();
        for (BookItem book : library.bookItems) {
            // Exact search with barCode
            if (book.getBarCode() == barCode) {
                books.add(book);
            }
        }
        return books;
    }

    public void addBookItem(BookItem bookItem) {
        if (!this.bookItems.contains(bookItem)) {
            this.bookItems.add(bookItem);
        }
    }

    public void removeBookItem(BookItem bookItem) {
        this.bookItems.remove(bookItem);
    }

    public ArrayList<Borrower> searchBorrower(String keyword) {
        ArrayList<Borrower> borrowers = new ArrayList<>();
        for (Borrower borrower : library.borrowers) {
            // Fuzzy search with keywords
            if (borrower.getFirstName().contains(keyword) || borrower.getLastName().contains(keyword)) {
                borrowers.add(borrower);
            }
        }
        return borrowers;
    }

    public ArrayList<Borrower> searchBorrower(int cardID) {
        ArrayList<Borrower> borrowers = new ArrayList<>();
        for (Borrower borrower : library.borrowers) {
            // Exact search with cardID
            if ((borrower.getCard().getId() == cardID)) {
                borrowers.add(borrower);
            }
        }
        return borrowers;
    }

    public void addBorrower(Borrower borrower) {
        if (borrowers.indexOf(borrower) < 0) {
            borrowers.add(borrower);
        }
    }

    public void removeBorrower(Borrower borrower) {
        borrowers.remove(borrower);
    }

    public void addManager(Manager manager) {
        if (managers.indexOf(manager) < 0) {
            managers.add(manager);
        }
    }

    public void removeManger(Manager manager) {
        managers.remove(manager);
    }

    @Override
    public String toString() {
        SimpleDateFormat sdf = new SimpleDateFormat("hh:mm a");
        return "name=" + name + ", location=" + location + ", openTime=" + sdf.format(openTime) + ", closeTime="
                + sdf.format(closeTime) + ", totalSits=" + totalSits + ", availableSits=" + availableSits;
    }

}
